###
 # 差分算法
 # 1、计算两个文件的大小，以最小文件为基础，从头开始进行比较。
 # 2、输出当前位置，不相等的长度，不相等的最新数据
 # 3、计算完前面部分的数据后，将后面的数据进行计算长度补充到刚才输出文件的后面
###

import struct
import os
def no_print(func):
    def wrapper(*args, **kwargs):
        import sys
        original_stdout = sys.stdout
        sys.stdout = open(os.devnull, 'w')
        result = func(*args, **kwargs)
        sys.stdout.close()
        sys.stdout = original_stdout
        return result
    return wrapper
def write_diff_block(file_handle, address, length, data):
    # 写入 address (int32), length (int32), data (bytes)
    file_handle.write(struct.pack('>I', address))     # 大端序 4字节整数
    file_handle.write(struct.pack('>H', length))      # 大端序 2字节整数
    file_handle.write(data)
@no_print
def generate_diff_file(old_filepath, new_filepath, diff_filepath):
    diff_block_begin = None
    diff_block_count = 0

    diff_file = open(diff_filepath, 'wb')
    #打开二进制文件
    with open(old_filepath, 'rb') as old_binfile, open(new_filepath, 'rb') as new_binfile:
        old_buffer = bytearray(old_binfile.read())
        new_buffer = bytearray(new_binfile.read())
    min_len = min(len(old_buffer), len(new_buffer))
    # 以最小文件的大小做为基准进行比较差分
    for i in range(min_len):
        if (old_buffer[i] != new_buffer[i]):
            if diff_block_begin is None:
                # 记录diff块起点
                diff_block_begin = i
                print("************diff begin************")
            # 统计diff块长度
            diff_block_count += 1
            print(f"diff count:{diff_block_count}")
            continue
        else:
            # 相同, 代表diff block结束
            if diff_block_begin is not None:
                print(f"diff block start index:{diff_block_begin}")
                print(f"diff_block_count:{diff_block_count}")
                print("************diff end************")
                print(f"diff data{new_buffer[diff_block_begin:diff_block_count]}")
                write_diff_block(diff_file, diff_block_begin, diff_block_count, new_buffer[diff_block_begin:diff_block_begin + diff_block_count])
                diff_block_begin = None
                diff_block_count = 0
    # 处理最后一个差异块
    if(len(old_buffer) < len(new_buffer)):
        print("最后一个位置:len", len(old_buffer), len(new_buffer) - len(old_buffer), new_buffer[len(old_buffer):len(new_buffer) - len(old_buffer)])
        write_diff_block(diff_file, len(old_buffer), len(new_buffer) - len(old_buffer), new_buffer[len(old_buffer):len(new_buffer)])
    # 关闭文件句柄
    old_binfile.close()
    new_binfile.close()
    diff_file.close()

if __name__ == '__main__':
    old_filepath='old_bin.bin'
    new_filepath='new_bin.bin'
    diff_filepath='diff_bin.bin'
    generate_diff_file( old_filepath, new_filepath, diff_filepath)
    print("#####Andy的差分算法-差分-2025-6-1#####")
    print(f"原始文件:{old_filepath}  原始文件大小:{os.path.getsize(old_filepath)}")
    print(f"新文件:{new_filepath}  新文件大小:{os.path.getsize(new_filepath)}")
    print(f"差分文件:{diff_filepath}  差分文件大小:{os.path.getsize(diff_filepath)}")
    print("差分完成")
    print("####################################")